package com.sinog.front.service.azbj.uploadappendix;

import com.alibaba.excel.util.FileUtils;
import com.sinog.core.model.UploadAppendixFile;
import com.sinog.core.model.UserDTO;
import com.sinog.core.util.JsonUtil;
import com.sinog.core.utilbean.Constants;
import com.sinog.core.utilbean.IdGen;
import com.sinog.core.utilbean.Result;
import com.sinog.core.utilbean.ReturnCode;
import com.sinog.front.feign.biz.BaseInfoService;
import com.sinog.front.feign.biz.FtpUtilService;
import com.sinog.front.feign.biz.UploadAppendixFileFeignService;
import com.sinog.front.service.user.UserFacade;
import com.sinog.front.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @desc 附件上传类
 * @author -
 * @date -
 */
@Service
@Slf4j
public class UploadAppendixFileService {

    private final static String UTF8 = "utf-8";
    @Resource
    private UploadAppendixFileFeignService uploadAppendixFileFeignService;
    @Autowired
    private UserFacade userFacade;
    @Resource
    private BaseInfoService baseInfoService;
    @Autowired
    private AsyncUploadFileToFtp asyncUploadFileToFtp;
    @Resource
    private FtpUtilService ftpUtilService;
    @Value("${gkzx.azbj.uploadFile.fileSuffix}")
    private String[] fileSuffix;
    /**
     * 上传文件
     * @param file file
     * @param id id
     * @param priNum priNum
     * @param taskId taskId
     * @param singleId singleId
     * @return Result
     */
    public Result saveAppendixFile(MultipartFile file,String id,String priNum,String taskId,String singleId) {
        UserDTO authentication = userFacade.getAuthentication();
        String fileName = file.getOriginalFilename();
        assert null != fileName;
        fileName = fileName.substring(fileName.lastIndexOf(File.separator) + 1);
        // 对于文件的后缀名进行判断
        String houzhui = fileName.substring(fileName.lastIndexOf("."));
        // 定义一个标志位
        boolean hzbs = false;
        String[] hz = fileSuffix;
        for(String s : hz) {
            if(s.equalsIgnoreCase(houzhui)) {
                hzbs = true;
                break;
            }
        }
        // 如果文件后缀名满足条件 可以执行下面的
        if (hzbs) {
            long dataId = IdGen.get().next();
            String tempFileName = authentication.getAccount() + File.separator + dataId + fileName.substring(fileName.lastIndexOf('.'));
            String filePath = FileUtil.getUploadFilePath() + tempFileName;
            File desFile = new File(filePath);
            if (!desFile.getParentFile().exists()) {
                try {
                    desFile.getParentFile().mkdirs();
                } catch (RuntimeException e) {
                    log.error(e.getMessage());
                }
            }
            //上传文件到本地磁盘后异步上传文件到ftp
            try {
                file.transferTo(desFile);
                // 获取ftp上传下载路径
                String datapath = ftpUtilService.getFtpClient().get("datapath");
                asyncUploadFileToFtp.uploadFileToFtp(datapath + authentication.getAccount(), filePath);
            } catch (IOException e) {
                log.error("发生异常:{}", e.getMessage());
            }
            UploadAppendixFile uploadAppendixFile = new UploadAppendixFile();
            uploadAppendixFile.setId(id);
            uploadAppendixFile.setSingleId(singleId);
            uploadAppendixFile.setTaskId(taskId);
            uploadAppendixFile.setPriNum(priNum);
            uploadAppendixFile.setFileName(fileName);
            uploadAppendixFile.setFileUrl(tempFileName);
            uploadAppendixFile.setAccount(authentication.getAccount());
            uploadAppendixFile.setUserName(authentication.getUsername());
            uploadAppendixFile.setUploadDate(new Date());
            uploadAppendixFileFeignService.saveAppendixFileData(uploadAppendixFile);
            return Result.success("保存成功");
        } else {
            return Result.failure(ReturnCode.SAVE_FAILED, "保存失败");
        }
    }

    /**
     * 查询流程中上传表单所有服务器端文件
     * @param pageIndex pageIndex
     * @param pageSize pageSize
     * @param map map
     * @return List<UploadAppendixFile>
     */
    public List<UploadAppendixFile> selectAllAppendixFile(Integer pageIndex,Integer pageSize,Map<String,Object> map) {
        return uploadAppendixFileFeignService.selectAppendixFileData(pageIndex,pageSize,map);
    }

    /**
     * 下载单个文件
     * @param request request
     * @param resp resp
     * @param fileUrl fileUrl
     * @param type type
     */
    public void downloadAppendixFile(HttpServletRequest request,HttpServletResponse resp,String fileUrl,String type) {
        try {
            if(Constants.NumberStr.NUM_STR_ONE.equalsIgnoreCase(type)) {
                String path = FileUtil.getUploadFilePath();
                ftpUtilService.downLoadFromFtp5(path + fileUrl,fileUrl);
                FileUtil.downloadFile(request,resp,path + fileUrl,fileUrl);
            } else if(Constants.NumberStr.NUM_STR_TWO.equalsIgnoreCase(type)) {
                // 获取ftp上传下载路径
                String sfbdatapath = ftpUtilService.getFtpClient().get("ftpDatapath");
                log.info("司法部ftp文件路径:{}",sfbdatapath);
                log.info("下载部级文件路径:{}",sfbdatapath + fileUrl);
                ftpUtilService.downLoadFromFtp(sfbdatapath + fileUrl,fileUrl);
                FileUtil.downloadFile(request,resp,fileUrl,fileUrl);
            }
        } catch(IOException e) {
            log.error("发生异常:{}",e.getMessage());
        }
    }

    /**
     * 系统管理-系统支持-文件查看
     * @param request request
     * @param response response
     * @param fileName 文件名称
     * @throws IOException
     */
    public void downloadVideo(HttpServletRequest request,HttpServletResponse response,String fileName) throws IOException {
        //需要从ftp中拉取
        //预先从本地服务拉取。先
        String path = FileUtil.getFileTemplatePath();
        String realPath = path + fileName;
        File file = new File(realPath);
        if(!file.exists()) {
            //return;
            //如果本地不存在，则去ftp服务器下载到服务器本地
            ftpUtilService.downLoadVideoFromFtp(fileName,realPath);
            file = new File(realPath);
            if(!file.exists()) {
                return;
            }
        }
        response.setCharacterEncoding(UTF8);
        InputStream is = null;
        OutputStream os = null;
        try {
            //分片下载
            long fSize = file.length();
            response.setContentType("application/x-download");
            String encodeFileName = URLEncoder.encode(fileName,UTF8);
            response.addHeader("Content-Disposition","attachment;filename=" + encodeFileName);
            response.setHeader("Accept-Range","bytes");
            response.setHeader("fSize",String.valueOf(fSize));
            response.setHeader("fName",encodeFileName);
            long pos = 0, last = fSize - 1, sum = 0;
            if(null != request.getHeader("Range")) {
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                String numRange = request.getHeader("Range").replaceAll("bytes=","");
                String[] strRange = numRange.split("-");
                if(strRange.length == 2) {
                    pos = Long.parseLong(strRange[0].trim());
                    last = Long.parseLong(strRange[1].trim());
                    if(last > fSize - 1) {
                        last = fSize - 1;
                    }
                } else {
                    pos = Long.parseLong(numRange.replaceAll("-","").trim());
                }
            }
            long rangeLenght = last - pos + 1;
            String contentRange = new StringBuffer("bytes ").append(pos).append("-").append(last).append("/")
                                                            .append(fSize).toString();
            response.setHeader("Content-Range",contentRange);
            response.setHeader("Content-Lenght",String.valueOf(rangeLenght));
            os = new BufferedOutputStream(response.getOutputStream());
            is = new BufferedInputStream(new FileInputStream(file));
            is.skip(pos);
            byte[] buffer = new byte[1024];
            int lenght = 0;
            while(sum < rangeLenght) {
                lenght = is.read(buffer,0,((rangeLenght - sum) <= buffer.length ? ((int)(rangeLenght - sum)) : buffer.length));
                sum = sum + lenght;
                os.write(buffer,0,lenght);
            }
            log.info("下载完成");
        } finally {
            if(is != null) {
                is.close();
            }
            if(os != null) {
                os.close();
            }
        }
    }

    /**
     * 批量下载文件-mysql版本
     * @param resp resp
     * @param request request
     * @param uploadAppendixFiles uploadAppendixFiles
     * @param type type
     */
    public void downloadAppendixAllFile(HttpServletResponse resp,HttpServletRequest request,List<UploadAppendixFile> uploadAppendixFiles,String type) {
        String path = FileUtil.getUploadFilePath();
        String datapath = ftpUtilService.getFtpClient().get("datapath");
        String sfbdatapath = ftpUtilService.getFtpClient().get("ftpDatapath");
        String jsonRestlt;
        Map<String,Object> resultMap;
        try {
            // 批量下载文件-mysql版本 - 各省下载本省
            String fileJson = JsonUtil.toText(uploadAppendixFiles);
            if(Constants.NumberStr.NUM_STR_ONE.equalsIgnoreCase(type)) {
                jsonRestlt = ftpUtilService.downLoadFromFtp6(fileJson,path,datapath);
                resultMap = JsonUtil.toMap(jsonRestlt);
                FileUtil.downloadFile(request,resp,(String)resultMap.get("filePath"),(String)resultMap.get("fileZip"));
                // 批量下载文件-mysql版本 - 各省下载司法部下发文件
            } else if(Constants.NumberStr.NUM_STR_TWO.equalsIgnoreCase(type)) {
                jsonRestlt = ftpUtilService.downLoadFromFtp6(fileJson,path,sfbdatapath);
                resultMap = JsonUtil.toMap(jsonRestlt);
                FileUtil.downloadFile(request,resp,(String)resultMap.get("filePath"),(String)resultMap.get("fileZip"));
            }
        } catch(IOException e) {
            log.info("UploadAppendixFileService--->downloadAppendixAllFile--->下载文件异常");
        }
    }

    /**
     * 删除上传文件
     * 1.删除服务器目录下文件
     * 2.删除mysql存储的文件信息
     * @param singleId singleId
     * @param fileUrl fileUrl
     * @param account account
     * @param priNum priNum
     * @return Result
     */
    public Result deleteAppendixFileOne(String singleId,String fileUrl,String account,String priNum) {
        UploadAppendixFile uploadAppendixFile = new UploadAppendixFile();
        //获取单个文件的唯一标识
        uploadAppendixFile.setSingleId(singleId);
        //获取用户账号
        uploadAppendixFile.setAccount(account);
        //获取用户账号
        uploadAppendixFile.setPriNum(priNum);
        //查询是否有该条目
        UploadAppendixFile uploadFile1 = uploadAppendixFileFeignService.findAppendixfileOne(uploadAppendixFile);
        if(null == uploadFile1) {
            return Result.failure(ReturnCode.DELETE_FILL_FAILED);
        }
        try {
            //如果有删除
            uploadAppendixFileFeignService.removeAppendixFileOne(uploadAppendixFile);
            File file = new File(FileUtil.getUploadFilePath() + fileUrl);
            boolean delete = file.delete();
            if(delete) {
                if(Constants.NumberStr.NUM_STR_TWO.equals(uploadFile1.getTaskId()) || Constants.NumberStr.NUM_STR_THREE.equals(uploadFile1.getTaskId())) {
                    //检测是否包含头像和指纹，如果无头像或无指纹了需要把temp修改
                    //根据犯罪编号和taskId查询文件表
                    Map<String,Object> map = new HashMap<>(16);
                    map.put("taskId",Constants.NumberStr.NUM_STR_TWO);
                    map.put("priNum",priNum);
                    int count1 = uploadAppendixFileFeignService.count(map);
                    map.put("taskId",Constants.NumberStr.NUM_STR_THREE);
                    int count2 = uploadAppendixFileFeignService.count(map);
                    if(Constants.Number.NUM_ZERO >= count1 || Constants.Number.NUM_ZERO >= count2) {
                        //更新临时表
                        uploadAppendixFileFeignService.changeTemp(map);
                        baseInfoService.updateStateI(priNum,Constants.NumberStr.NUM_STR_ZERO);
                    }
                }
                return Result.success("删除成功！");
            }
        } catch(RuntimeException e) {
            log.error("发生异常:",e);
        }
        return Result.failure(ReturnCode.DELETE_FILL_FAILED);
    }

    /**
     * 司法所衔接选择失败后将之前上传的公安附件删除
     * @param priNum priNum
     * @param id id
     * @return Result
     */
    public Result deleteUploadFile(String priNum,String id) {
        int i = uploadAppendixFileFeignService.deleteUploadFile(priNum,id);
        if(0 < i) {
            return Result.success("删除成功");
        }
        return Result.failure(ReturnCode.DELETE_FAILED);
    }

    /**
     * 描述
     * @param request request
     * @param resp resp
     * @param uploadAppendixFile uploadAppendixFile
     * @param type type
     */
    public void downloadAppendixFileSingle(HttpServletRequest request,HttpServletResponse resp,UploadAppendixFile uploadAppendixFile,String type) {
        try {
            String path = FileUtil.getUploadFilePath();
            String sfbdatapath = ftpUtilService.getFtpClient().get("ftpDatapath");
            if(Constants.NumberStr.NUM_STR_TWO.equalsIgnoreCase(type)) {
                String[] file = uploadAppendixFile.getFileUrl().split("/");
                String filepath = path + file[1];
                log.info("司法部ftp文件路径:{}",sfbdatapath);
                log.info("下载到本地的文件路径:{}",path);
                ftpUtilService.downLoadFromFtp3(uploadAppendixFile,path,sfbdatapath);
                FileUtil.downloadFile(request,resp,filepath,file[1]);
            }
        } catch(Exception e) {
            log.error("发生异常:",e);
        }
    }

    /**
     * 查询文件数量
     * @param priNum priNum
     * @param taskId taskId
     * @return Result 文件的数量
     */
    public Result getCountAll(String priNum,String taskId) {
        Map<String,Object> map = new HashMap<>(16);
        map.put("taskId",taskId);
        map.put("priNum",priNum);
        int count1 = uploadAppendixFileFeignService.count(map);
        return Result.success(count1);
    }

    /**
     * 根据id priNum taskId查询上传文件数量
     * @param priNum 罪犯编号
     * @param id 随机id
     * @param taskId 业务标识
     * @return Result
     */
    public Result getCountById(String priNum,String id,String taskId) {
        Map<String,Object> map = new HashMap<>(16);
        map.put("taskId",taskId);
        map.put("priNum",priNum);
        map.put("id",id);
        int count1 = uploadAppendixFileFeignService.getCountById(map);
        return Result.success(count1);
    }

    /**
     * 根据id priNum taskId删除单个上传文件
     * @param priNum 犯罪编号
     * @param id 唯一id
     * @param taskId 业务标识
     * @return Result
     */
    public Result deleteById(String priNum,String id,String taskId) {
        Map<String,Object> map = new HashMap<>(16);
        map.put("taskId",taskId);
        map.put("priNum",priNum);
        map.put("id",id);
        int count1 = uploadAppendixFileFeignService.deleteFileById(map);
        return Result.success(count1);
    }

    /**
     * 断点续传-上传文件
     * @param request request
     * @param response response
     * @return Result
     */
    public Result uploadFileToFtpRemote(HttpServletRequest request,HttpServletResponse response) {
        log.info("---培训资料本地上传文件开始---");
        //分片
        response.setCharacterEncoding(UTF8);
        //分片
        Integer schunk = null;
        //总分片
        Integer schunks = null;
        String name = null;
        String desc = null;
        String uploadPath = FileUtil.getFileTemplatePath();
        BufferedOutputStream os = null;
        try {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(1024);
            factory.setRepository(new File(uploadPath));
            ServletFileUpload upload = new ServletFileUpload(factory);
            //设置每个文件大小
            upload.setFileSizeMax(5L * 1024L * 1024L * 1024L);
            //设置总大小
            upload.setSizeMax(10L * 1024L * 1024L * 1024L);
            List<FileItem> items = upload.parseRequest(request);
            for(FileItem item : items) {
                if(item.isFormField()) {
                    if("chunk".equals(item.getFieldName())) {
                        schunk = Integer.parseInt(item.getString(UTF8));
                    }
                    if("desc".equals(item.getFieldName())) {
                        desc = item.getString(UTF8);
                    }
                    if("chunks".equals(item.getFieldName())) {
                        schunks = Integer.parseInt(item.getString(UTF8));
                    }
                    if("name".equals(item.getFieldName())) {
                        name = item.getString(UTF8);
                    }
                }
            }
            for(FileItem item : items) {
                if(!item.isFormField()) {
                    String temFileName = name;
                    if(name != null) {
                        if(schunk != null) {
                            temFileName = schunk + "_" + name;
                        }
                        File temFile = new File(uploadPath,temFileName);
                        //断点续传
                        if(!temFile.exists()) {
                            item.write(temFile);
                        }
                    }
                }
            }
            //文件合并
            if(schunk != null && schunk.intValue() == schunks.intValue() - 1) {
                File tempFile = new File(uploadPath,name);
                os = new BufferedOutputStream(new FileOutputStream(tempFile));
                for(int i = 0; i < schunks; i++) {
                    File file = new File(uploadPath,i + "_" + name);
                    while(!file.exists()) {
                        Thread.sleep(100);
                    }
                    byte[] bytes = FileUtils.readFileToByteArray(file);
                    os.write(bytes);
                    os.flush();
                    file.delete();
                }
                os.flush();
            }
        } finally {
            try {
                if(os != null) {
                    os.close();
                }
            } catch(IOException e) {
                e.printStackTrace();
            }
            log.info("---培训资料本地上传文件结束:{}---",name);
            String uploadFilePathName = uploadPath + name;
            return ftpUtilService.uploadFileToFtpRemote(name,uploadFilePathName,desc);
        }
    }

    /**
     * 运维管理-视频管理-查询所有的培训资料
     * @param flag 状态吗 0：上架 1：下架
     * @return String
     */
    public String selectAllVideos(String flag) {
        return ftpUtilService.selectAllVideos(flag);
    }

    /**
     * 更改文件状态
     * @param name 文件名称
     * @return Result
     */
    public Result updateStatus(String name,String status) {
        return ftpUtilService.updateVideo(name,status);
    }

    /**
     * 删除文件
     * @param name 文件名称
     * @return Result
     */
    public Result deleteLocalFile(String name) {
        String uploadPath = FileUtil.getFileTemplatePath();
        String uploadFilePathName = uploadPath + name;
        return ftpUtilService.delete(uploadFilePathName,name);
    }
}